RFCに準拠したHTTPヘッダ比較について
概要
RFCに反してるライブラリ使ってハマってた。
何が起こったか
httpのヘッダのキーに大文字小文字でフル一致できる文字列が入っているはず、という
謎の期待をするクライアント実装があって、
それを知らずに使っていたため通信結果が失敗に終わるという感じで、なかなか真相に気づかずにハマった。
対象のライブラリはこちら。
websocket-sharp
https://github.com/sta/websocket-sharp
困ってた部分のコードはこんな感じになっている。
WebSocket.cs
var headers = response.Headers;
if (!validateSecWebSocketAcceptHeader (headers["Sec-WebSocket-Accept"])) {
message = "Includes no Sec-WebSocket-Accept header, or it has an invalid value.";
return false;
}
if (!validateSecWebSocketProtocolServerHeader (headers["Sec-WebSocket-Protocol"])) {
message = "Includes no Sec-WebSocket-Protocol header, or it has an invalid value.";
return false;
}
if (!validateSecWebSocketExtensionsServerHeader (headers["Sec-WebSocket-Extensions"])) {
message = "Includes an invalid Sec-WebSocket-Extensions header.";
return false;
}
if (!validateSecWebSocketVersionServerHeader (headers["Sec-WebSocket-Version"])) {
message = "Includes an invalid Sec-WebSocket-Version header.";
return false;
}
この内容と大文字小文字がジャストマッチしてないと、WebSocket接続のハンドシェイクが失敗に終わる。
対して、WebSocketのRFCの基準はこちら
https://tools.ietf.org/html/rfc6455#section-2.1
…
Comparing two strings in an _ASCII case-insensitive_ manner means
comparing them exactly, code point for code point, except that the
characters in the range U+0041 to U+005A (i.e., LATIN CAPITAL LETTER
A to LATIN CAPITAL LETTER Z) and the corresponding characters in the
range U+0061 to U+007A (i.e., LATIN SMALL LETTER A to LATIN SMALL
LETTER Z) are considered to also match.
…
文字列比較について、特に_ASCII case-insensitive_って書いてあるところはこうすべきだよ~みたいな但し書きがあって、
・大文字だろうが小文字だろうがマッチすること
という感じになっている。
というわけで、修正したものをプルリク済み。
https://github.com/sta/websocket-sharp/pull/315
ちなみに一切テストコードが存在しないんで、まあ、なんだ、、一度手元で動かしたけど確証はないので、つらい。